﻿using System;
using System.Collections;
using System.Configuration;
using System.Reflection;
using System.Web;
using System.Web.Configuration;
using System.Web.UI.WebControls;

namespace Salient.Web.Administration.Providers
{
    public partial class ManageProviders : ProvidersPage
    {
        public void BackToPreviousPage(object sender, EventArgs e)
        {
            ReturnToPreviousPage(sender, e);
        }

        private void BindProviderList(ProviderSettingsCollection providers,
                                      string defaultProvider,
                                      ProviderList providerList)
        {
            var providersArray = new ArrayList();

            foreach (ProviderSettings mps in providers)
            {
                string name = mps.Name;
                string connectionString = mps.Parameters["connectionStringName"];
                providersArray.Add(new ProviderList.ProviderListItems(mps.Name, mps.Parameters["description"],
                                                                      mps.Parameters["connectionStringName"], mps.Type,
                                                                      false));
            }

            providerList.DataSource = providersArray;

            int i = 0;
            foreach (ProviderSettings ps in providers)
            {
                if (ps.Name == defaultProvider)
                {
                    providerList.SelectedIndex = i;
                }
                i++;
            }
            providerList.DataBind();
        }

        private void BindProviderLists()
        {
            System.Configuration.Configuration config = OpenWebConfiguration(ApplicationPath);

            var membershipSection = (MembershipSection) config.GetSection("system.web/membership");
            MembershipProviderList.ParentProviderCount = ParentProviderCount("membership");
            BindProviderList(membershipSection.Providers, membershipSection.DefaultProvider, MembershipProviderList);

            var roleManagerSection = (RoleManagerSection) config.GetSection("system.web/roleManager");
            RoleProviderList.ParentProviderCount = ParentProviderCount("roleManager");
            BindProviderList(roleManagerSection.Providers, roleManagerSection.DefaultProvider, RoleProviderList);
        }

        private void Page_Load()
        {
            if (!IsPostBack)
            {
                BindProviderLists();
            }
        }

        public void SelectProvider(object sender, ProviderList.ProviderEventArgs e)
        {
            var radioButton = (RadioButton) sender;

            System.Configuration.Configuration config = OpenWebConfiguration(ApplicationPath);
            switch (e.ServiceName)
            {
                case "membership":
                    var membershipSection = (MembershipSection) config.GetSection("system.web/membership");
                    membershipSection.DefaultProvider = e.ProviderName;
                    break;
                case "roleManager":
                    var roleManagerSection = (RoleManagerSection) config.GetSection("system.web/roleManager");
                    roleManagerSection.DefaultProvider = e.ProviderName;
                    break;
                default:
                    throw new HttpException(String.Format((string) GetLocalResourceObject("UnrecognizedService"),
                                                          e.ServiceName));
            }

            SaveConfig(config);
            BindProviderLists();
        }

        private int ParentProviderCount(string serviceName)
        {
            string parentPath = GetParentPath(ApplicationPath);
            System.Configuration.Configuration parentConfig = OpenWebConfiguration(parentPath);
            switch (serviceName)
            {
                case "membership":
                    var membershipSection = (MembershipSection) parentConfig.GetSection("system.web/membership");
                    return membershipSection.Providers.Count;
                case "roleManager":
                    var roleManagerSection = (RoleManagerSection) parentConfig.GetSection("system.web/roleManager");
                    return roleManagerSection.Providers.Count;
                default:
                    return -1;
            }
        }

        private bool TestConnectionHelper(string connection)
        {
            bool good = true;
            try
            {
                Type type = typeof (HttpApplication).Assembly.GetType("System.Web.DataAccess.SqlConnectionHelper");
                MethodInfo method = type.GetMethod("GetConnection",
                                                   BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                if (method != null)
                {
                    method.Invoke(null, new object[] {connection, false /* revert impersonation */});
                }
            }
            catch
            {
                good = false;
            }
            return good;
        }

        private bool TestConnectionString(object sender, EventArgs e)
        {
            var b = sender as LinkButton;
            string connectionString = null;
            try
            {
                System.Configuration.Configuration config = OpenWebConfiguration(ApplicationPath);
                var connectionStringSection = (ConnectionStringsSection) config.GetSection("connectionStrings");
                // Review: Management API doesn't allow retrieve a connection string setting via direct name look up
                // Need to create an object with the name set for looking up instead.
                var css = new ConnectionStringSettings();
                css.Name = b.CommandArgument /* connection string name */;
                css = connectionStringSection.ConnectionStrings[connectionStringSection.ConnectionStrings.IndexOf(css)];
                connectionString = css.ConnectionString;
            }
            catch
            {
                return false;
            }

            if (b.CommandName.Contains("Sql"))
            {
                return TestConnectionHelper(connectionString);
            }
            else
            {
                return true;
            }
        }

        public void TestConnection(object sender, EventArgs e)
        {
            bool good = TestConnectionString(sender, e);
            var b = (LinkButton) sender;
            bool isSql = b.CommandName.Contains("Sql");
            bool isWindowsToken = b.CommandName.Contains("WindowsToken");
            if (isWindowsToken)
            {
                good = true;
            }

            mv1.ActiveViewIndex = 1;
            testConnectionLiteral.Text = TestConnectionText(good, isSql);

            OKButton.Visible = true;
            ((WebAdminWithConfirmation) Master).SetDisplayUI(true /* confirmation */);
        }

        public void OK_Click(object sender, EventArgs e)
        {
            ((WebAdminWithConfirmation) Master).SetDisplayUI(false);
        }
    }
}